﻿using Core.AppExtensions.Attributes;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Core.AppExtensions
{
    /// <summary>
    /// 自动注入类,所有未被标记为SkipScanAttribute的public类之下的服务注入方法都会通过本类的全部的方法执行自动扫描注入
    /// </summary>
    [SkipScan]
    public static class AutoServices
    {
        /// <summary>
        /// 自动add服务的方法
        /// </summary>
        /// <param name="services"></param>
        public static void AutoAddServices(this IServiceCollection services)
        {
            var EffectiveType = App.GetTypes();
            object[] paramsobj = new object[1] { services };
            foreach (Type type in EffectiveType.Where(t => t.GetCustomAttribute(typeof(SkipScanAttribute)) == null))
            {
                //获取所有的静态服务方法且第一个参数为IServiceCollection类型的方法，并自动执行
                var MethodInfos = type.GetMethods()
                    .Where(t => t.IsPublic
                    && t.IsStatic
                    && t.ReturnType == typeof(void)
                    && t.GetParameters().Length == 1
                    && t.GetParameters().First().ParameterType == typeof(IServiceCollection)
                    && t.GetCustomAttribute<SkipScanAttribute>()== null);
                if (!MethodInfos.Any()) continue;
                foreach (var method in MethodInfos)
                {
                    method.Invoke(type, paramsobj);
                }
            }
        }

        /// <summary>
        /// 自动use服务的方法
        /// </summary>
        /// <param name="app"></param>
        public static void AutoUseServices(this IApplicationBuilder app)
        {
            var EffectiveType = App.GetTypes();
            foreach (Type type in EffectiveType.Where(t => t.GetCustomAttribute(typeof(SkipScanAttribute)) == null))
            {
                //获取所有的静态服务方法且第一个参数为IApplicationBuilder类型的方法，并自动执行
                var MethodInfos = type.GetMethods()
                    .Where(t => t.IsPublic
                    && t.IsStatic
                    && t.ReturnType == typeof(void)
                    && t.GetParameters().Length >= 1
                    && t.GetParameters().First().ParameterType == typeof(IApplicationBuilder)
                    && t.GetCustomAttribute<SkipScanAttribute>() == null);
                if (!MethodInfos.Any()) continue;
                foreach (var method in MethodInfos)
                {
                    bool CanInvoke = true;
                    int ParamsCount = method.GetParameters().Length;
                    object[] Paramsobjs = new object[ParamsCount];
                    for (int i = 0; i <= ParamsCount - 1; i++)
                    {
                        if (i == 0)
                        {
                            Paramsobjs[i] = app;
                        }
                        else
                        {
                            var obj = app.ApplicationServices.GetService(method.GetParameters()[i].ParameterType);
                            if (obj != null)
                            {
                                Paramsobjs[i] = obj;
                            }
                            else
                            {
                                CanInvoke = false;
                                break;
                            }
                        }
                    }
                    if (CanInvoke)
                    {
                        method.Invoke(type, Paramsobjs);
                    }

                }
            }
        }
        /// <summary>
        /// 自动注入builder的方法
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IHostBuilder AutoBuild(this IHostBuilder builder)
        {
            var EffectiveType = App.GetTypes();
            object[] paramsobj = new object[1] { builder };
            foreach (Type type in EffectiveType.Where(t => t.GetCustomAttribute(typeof(SkipScanAttribute)) == null))
            {
                //获取所有的静态服务方法且第一个参数为IHostBuilder类型的方法，并自动执行
                var MethodInfos = type.GetMethods()
                    .Where(t => t.IsPublic
                    && t.IsStatic
                    && t.ReturnType == typeof(IHostBuilder)
                    && t.GetParameters().Length == 1
                    && t.GetParameters().First().ParameterType == typeof(IHostBuilder)
                    && t.GetCustomAttribute<SkipScanAttribute>() == null);
                if (!MethodInfos.Any()) continue;
                foreach (var method in MethodInfos)
                {
                    method.Invoke(type, paramsobj);
                }
            }
            return builder;
        }

    }
}
